==============
  BlitzSmash
==============

1. Grundverhalten
=================
Wtet nicht wild in den einzelnen Dateien herum, jeder Datei ist eine bestimmte Funktion zugeteilt:

Grundlegender Spielablauf
main.bb
titlescreen.bb

Types:
attack.bb
dust.bb
level.bb
player.bb

Engine:
camera.bb
Draw3D.bb by hectic
physics.bb

Data (selbstgemachte Levels, Spieler etc):
attackdata.bb
leveldata.bb
playerdata.bb

Alle Dateien sind im <main program> includet und knnen Const und Function enthalten. Man sollte es mglichst vermeiden Lokale oder Globale Variablen zu definieren, sondern sollte mittels Const auf die bnkInfo des Types, den man bearbeitet zugreifen. Die Banks mglichst spt erstellen, sodass man nicht eine 200er Bank im Spiel hat, die nicht genutzt wird.

2. Label2 und GoSub2
====================

Die Funktionszeiger.dll von Noobody macht es mglich Labels in Variablen zu speichern.
Einen Label definiert man wie folgt:

tmp=Label2()
If proginit
  lblVariable=tmp
Else
  <CODE>
  Return
EndIf

Die Variable proginit ist vor den Includes 1 und danach 0. Das fhrt dazu, dass die Variable lblVariable beim Include gesetzt wird aber <CODE> nicht ausgefhrt wird. Wird spter im Code folgendes ausgefhrt:

GoSub2 lblVariable

Dann springt der Code an diese Stelle:

tmp=<---

Das heit tmp erhllt irgendeinen Wert, weil Label2 nicht ausgefhrt wird. Deshalb darf lblVariable nur whrend proginit=1 ist gesetzt werden, da es sonst mit diesem Wert berschrieben werden wrde. Da die GoSub2 erst in der Hauptschleife ausgefhrt werden ist proginit=0 und es wird <CODE> ausgefhrt und mit Return zurckgesprungen.

3. Einen Player erstellen
=========================
in der Datei playerdata.bb ist folgendes einzugeben:

;<NAME DES CHARAKTRS>

Const PLAYER_NAME_Variable=0;=Bankoffset

c.character=New character
c\name="<NAME DES CHARAKTRS>"

tmp=Label2();input: c.character ;output:p.player
If proginit
	c\lblInit=tmp
Else
	;lblInit wird bei der Charakterwahl ausgefhrt. Ein Level l ist
 	;noch nicht gesetzt. Aufgabe der lblInit eines Charaktrs ist es 
	;einen p.player zu erstellen und ihn spielbereit zu laden.
	
	;Der folgede Teil ist immer gleich
	p=New player
	p\bnkInfo=CreateBank(4) ;/!\ Die Bankgre nach Bedarf anpassen
					;Dran denken: Ein Handle (zB von Models)
 					;ist 4 Byte gro.

	p\phx=New phxEntity	;Hier wird Der Spieler als Physikalisches
 					;Objekt erstellt, dass der Schwerkraft
 					;unterliegt und sterben kann.
	p\phx\entModel=CreatePivot()
					;Dieser Pivot ist Pflicht und dient
 					;als Kollisions-Entity
	p\c=c				;Dem Spieler den Charakter zuweisen
	EntityType p\phx\entModel,COLLISION_PLAYER
	EntityPickMode p\phx\entModel,1	;} Wichtig fr Attacken.
	NameEntity p\phx\entModel,Handle(p)	;}
	
	;Beispiel fr das Aussehen des Players

	PokeInt p\bnkInfo,PLAYER_NAME_Variable,CreateCube(p\phx\entModel)
	;Anstelle von Variable=CreateCube(p\phx\entModel)

	EntityColor PeekInt(p\bnkInfo,PLAYER_NAME_Variable),255,0,0	
	;Anstelle von EntityColor Variable,255,0,0

	Return
EndIf	
	
tmp=Label2();input: btnRight,btnLeft,btnUp,btnDown,btnAtt1,btnAtt2,btnSmash,p.player
If proginit
	c\lblMovement=tmp
Else
	;lblMovement wird in der Hauptschleife fr jeden teilnehmenden
 	;Spieler ausgefhrt. Die Buttons Right und Left sind durch Downs 
	;und alle anderen nur durch Hits abgefragt.
	;Einen Smash fhrt der Spieler aus, wenn er innerhalb von 100ms 
	;die Taste btnAtt1 nochmal drckt. Denke dran, dass whrend der 
	;Spieler stoned ist, er keine Tasten drcken kann.
	;Beispiel: Player 1 drckt btnAtt1
	;Das Spiel beginnt mit der Animation von btnAtt1 und setzt 	;tmeStoned auf Millisecs()+50
	;Nun muss der Spieler zwischen 50 und 100 ms nach seinem 
	;ersten Tastendruck erneut anschlagen. Das soll durchaus sehr 	;knifflig sein. Deshalb drfen Smash-Attacken auch ruhig etwas 	;strker sein (zB. 20-30% geben).
	
	
	If btnRight
		p\phx\ax=p\phx\ax+0.7;Den Spieler beschleunigen
		RotateEntity p\phx\entModel,0,-90,0	;Den Spieler Drehen,
								;sodass er in die
 								;Laufrichtugn schaut
	
	;Beispiel fr Animationssteuerung der Meshs beim Laufen.
	;If Not Animating(PeekInt(p\bnkInfo,PLAYER_PLAYER_NAME_ANIM))
	;	Animate PeekInt(p\bnkInfo,PLAYER_NAME_ANIM),1,0.5
	;EndIf

	EndIf
	
	If btnLeft
		p\phx\ax=p\phx\ax-0.7;Den Spieler beschleunigen
		RotateEntity p\phx\entModel,0,90,0  ;Den Spieler Drehen,
								;sodass er in die 
								;Laufrichtugn schaut

	;Beispiel fr Animationssteuerung der Meshs beim Laufen.
	;If Not Animating(PeekInt(p\bnkInfo,PLAYER_PLAYER_NAME_ANIM))
	;	Animate PeekInt(p\bnkInfo,PLAYER_NAME_ANIM),1,0.5
	;EndIf

	EndIf
	
	If btnUp
		p\phx\ay=p\phx\ay+10;Nach oben beschleunigen
	EndIf
	
	If btnDown
		p\phx\ay=p\phx\ay-10;Nach unten beschleunigen
	EndIf
	
	If btnAtt1 ;Beispiel-Atacke: Kick
		If EntityYaw(p\phx\entModel)>0 ;je nachdem wohin man schaut
			
ATTACK_KICK_Damage(p,-Reichweite,Schaden,-xBeschl,yBeschl)

		Else

ATTACK_KICK_Damage(p,-Reichweite,Schaden,+xBeschl,yBeschl)

		EndIf
		p\tmeStoned=MilliSecs()+50	;Fr 50 Millisec ist der 							;Spieler blockiert.
	EndIf
	
	If btnAtt2
		;Auch eine Attacke
	EndIf
	
	If btnSmash
		;Auch eine Attacke
	EndIf
	
	;Hier kann noch anderer Code, wie Attacken-Bewegungen etc hin.

	;Beispiel fr Animationssteuerung
	;If p\tmeStoned<MilliSecs()
	;	If Not(btnRight Or btnLeft) 
	;		Animate PeekInt(p\bnkInfo,PLAYER_NAME_ANIM),0
	;	EndIf
	;EndIf
	
	Return
EndIf

4. Ein Level erstellen
======================

In der Datei leveldata.bb ist folgendes einzugeben:
;<Level-Name>
Const LEVEL_NAME_Variable=0;Bank-Offset

l.level=New level
l\maxx=600	;Beispielmae
l\minx=-600	;fr
l\maxy=200	;ein
l\miny=-100	;Level
l\name="<Level-Name>"

tmp=Label2()
If proginit
	l\lblInit=tmp
Else
	;lblInit wird einmalig vor der Hauptschleife ausgefhrt nachdem
 	;alle Spieler dem Spiel beigetreten sind.

	l\bnkInfo=CreateBank(4);/!\Bankgre anpassen
	
	;Mindestens ein Gegenstand sollte es geben mit dem der Spieler 	;mittels Kugel-Poly-Kollision Kollidieren kann.
	PokeInt l\bnkInfo,LEVEL_NAME_Variable,CreateCube()
	EntityType PeekInt(l\bnkInfo,LEVEL_NAME_Variable),COLLISION_LEVEL	EntityScale PeekInt(l\bnkInfo,LEVEL_NAME_Variable),100,10,10
	
	;Wichtig ist, dass alle 4 Spawnpunkte so Initialisiert werden.
	;Man knnte auch mehr als 4 Spawnpunkte erstellen.
	spawn[0] = New SpawnPoint
	spawn[0]\x=-200
	spawn[0]\y=100
	
	spawn[1] = New SpawnPoint
	spawn[1]\x=-100
	spawn[1]\y=100
	
	spawn[2] = New SpawnPoint
	spawn[2]\x=100
	spawn[2]\y=100
	
	spawn[3] = New SpawnPoint
	spawn[3]\x=200
	spawn[3]\y=100
	
	Return
EndIf

tmp=Label2()
If proginit
	l\lblLevel=tmp
Else
	;lblLevel wird in der Hauptschleife nach lblMovement ausgefhrt.
	;l und currentlevel enthalten die Level-Variable. Hier kann man
 	;Code schreiben, sodass sich das Level bewegt oder interagiert.
	
	Return
EndIf

5. Attacken erstellen
=====================
in der ersten Zeile der attackdata.bb steht:
Global ATTACK_KICK.AttackType,...

Hier die eigene Attacke in der Form ATTACK_NAME hinzufgen. 
Dann ans Ende der Datei

;<Attacken-Name>
Const ATTACK_NAME_Variable=0;Bank-Offset

ATTACK_NAME=New Attacktype;wurde bei Global schon eingefhrt
;ATTACK_NAME\bnkInfo=CreateBank(0)
;Evtl knnen hier schon Texturen oder Entitys fr eine solche Attacke
;geladen werden. Diese sollten aber zunchst unsichtbar sein.

tmp=Label2()
If proginit
	ATTACK_KICK\lblMovement=tmp
Else
	;lblMovement wird ausgefhrt wenn ein Spieler eine Attacke
 	;ausfhrt. *Wenn die Attacke beendet wird muss sie sich selbst
 	;lschen.*
	
	;Tipps:
	
	;Reichweite in einem Byte Speichern
	tmp=PeekByte(a\bnkInfos,ATTACK_NAME_DISTANCE)
	If tmp>128 Then tmp=tmp-256;unsinged Byte->signed byte
	;Einfach mit PokeByte reinschreiben und so auslesen	

	;Einen Gegner finden:
	;Am einfachsten geht das mit einer Pick-Methode, da jeder
 	;Charakter mit seinem Kollisions-Entity Pickbar ist und seine
 	;player-Handle als Namen dieses Models trgt

	;Beispiel:
	LinePick x,y,0,distancex,distancey,0,radius
	
	If PickedEntity()<>0
		p.player=Object.player(EntityName(PickedEntity()));p=Ziel
		If p<>Null
			Damage(p,prozent,xBeschl,yBeschl)
		EndIf
	EndIf
	
	Delete a	;Nach Beendigung der Attacke muss sie sich lschen.
			;Eine Attacke kann natrlich auch mehrere Frames
 			;andauern.
	
	Return
EndIf

;Hilfsfunktionen knnen ntzlich sein um Banks zu fllen etc.
;Hier zB die Hilfsfunkiton zu KICK. Innerhalb von Hilfsfunktionen sind ;lokale Variablen erlaubt.
Function ATTACK_KICK_Damage(p.player,distance,percent,ax#,ay#)
	Local a.Attack
	a=New Attack
	a\at=ATTACK_KICK
	a\bnkInfos=CreateBank(ATTACK_KICK_SIZE)
	PokeFloat a\bnkInfos,ATTACK_KICK_X,EntityX(p\phx\entModel)
	PokeFloat a\bnkInfos,ATTACK_KICK_Y,EntityY(p\phx\entModel)
	PokeByte a\bnkInfos,ATTACK_KICK_DISTANCE,distance
	PokeByte a\bnkInfos,ATTACK_KICK_PERCENT,percent
	PokeFloat a\bnkInfos,ATTACK_KICK_AX,ax
	PokeFloat a\bnkInfos,ATTACK_KICK_AY,ay
End Function